/*
 * Copyright 2010 - 2011, The PLDesktop Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */
#ifndef _C_STDLIB_H
#define _C_STDLIB_H

#include <stddef.h>
#if defined __cplusplus
using namespace std;
#ifdef EXPORT_LOCAL
#undef EXPORT_LOCAL
#endif
#define EXPORT_LOCAL extern "C"
#else
#define EXPORT_LOCAL extern
#endif

#define __THROW

#define unreachable() (abort())

#define CVTBUFSIZE        (309 + 43)

#if defined __cplusplus
namespace std {
#endif

	/**
	 * Type flags to use for the number conversion.
	 */
	enum NumberTypes {
		/**
		 * Pad with zero.
		 */
		ZEROPAD         = 1 << 0,
		/**
		 * Unsigned/signed long
		 */
		SIGN			= 1 << 1,
		/**
		 * Show plus
		 */
		PLUS			= 1 << 2,
		/**
		 * Space if plus
		 */
		SPACE			= 1 << 3,
		/**
		 * Left justified
		 */
		LEFT			= 1 << 4,
		/**
		 * 0x hex value
		 */
		SPECIAL         = 1 << 5,
		/**
		 * Use 'ABCDEF' instead of 'abcdef'
		 */
		LARGE			= 1 << 6
	};

    #define S_FORMAT_STAR		1
    #define S_FORMAT_LONG		2
    #define S_FORMAT_LONGLONG	4
    #define S_FORMAT_UNSIGNED	8

	EXPORT_LOCAL void __abort_fail(const char *file, unsigned int line, const char *function);
	EXPORT_LOCAL void abort();

	/**
	 * Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
	 *
	 * @param size Size of the memory block, in bytes.
	 */
	EXPORT_LOCAL void *malloc(size_t size);
	/**
	 * Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
	 *
	 * @param size Size of the memory block, in bytes.
	 */
	EXPORT_LOCAL void *alloca(size_t size);
	/**
	 * The size of the memory block pointed to by the ptr parameter is changed to the size bytes, expanding
	 * or reducing the amount of memory available in the block.
	 *
	 * @param ptr Pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated.
	 * If this is NULL, a new block is allocated and a pointer to it is returned by the function.
	 * @param size New size for the memory block, in bytes.
	 * If it is 0 and ptr points to an existing block of memory, the memory block pointed by ptr is
	 * deallocated and a NULL pointer is returned.
	 */
	EXPORT_LOCAL void *realloc(void *ptr, size_t size);
	/**
	 * A block of memory previously allocated using a call to malloc, calloc or realloc is deallocated,
	 * making it available again for further allocations.
	 *
	 * @param el Pointer to a memory block previously allocated with malloc, calloc or realloc to be deallocated.
	 * If a null pointer is passed as argument, no action occurs.
	 */
	EXPORT_LOCAL void free(void *el);
    /**
     * Convert string to double<br>
     * Parses the C string str interpreting its content as a floating point number and returns its value as a double.<br>
     * The function first discards as many whitespace characters as necessary until the first non-whitespace character
     * is found. Then, starting from this character, takes as many characters as possible that are valid following a
     * syntax resembling that of floating point literals, and interprets them as a numerical value. The rest of the
     * string after the last valid character is ignored and has no effect on the behavior of this function.<br>
     * A valid floating point number for atof is formed by a succession of:<br>
     * - An optional plus or minus sign<br>
     * - A sequence of digits, optionally containing a decimal-point character<br>
     * - An optional exponent part, which itself consists on an 'e' or 'E' character followed by an optional sign
     * and a sequence of digits.<br>
     * If the first sequence of non-whitespace characters in str does not form a valid floating-point number as
     * just defined, or if no such sequence exists because either str is empty or contains only whitespace characters,
     * no conversion is performed.
     *
     * @param str C string beginning with the representation of a floating-point number.
     * @return On success, the function returns the converted floating point number as a double value.<br>
     * If no valid conversion could be performed, or if the correct value would cause underflow, a zero value (0.0) is returned.<br>
     * If the correct value is out of the range of representable values, a positive or negative HUGE_VAL is returned.
     */
    EXPORT_LOCAL double atof(const char *str);
    /**
     * Convert string to integer.<br>
     * Parses the C string str interpreting its content as an integral number, which is returned as an int value.<br>
     * The function first discards as many whitespace characters as necessary until the first non-whitespace character
     * is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many
     * numerical digits as possible, and interprets them as a numerical value.<br>
     * The string can contain additional characters after those that form the integral number, which are ignored and
     * have no effect on the behavior of this function.<br>
     * If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence
     * exists because either str is empty or it contains only whitespace characters, no conversion is performed.
     *
     * @param str C string beginning with the representation of an integral number.
     * @return On success, the function returns the converted integral number as an int value.<br>
     * If no valid conversion could be performed, a zero value is returned.<br>
     * If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.
     */
    EXPORT_LOCAL int atoi(const char *str);
    /**
     * Convert string to long integer.<br>
     * Parses the C string str interpreting its content as an integral number, which is returned as a long int value.<br>
     * The function first discards as many whitespace characters as necessary until the first non-whitespace character
     * is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many
     * numerical digits as possible, and interprets them as a numerical value.<br>
     * The string can contain additional characters after those that form the integral number, which are ignored and
     * have no effect on the behavior of this function.<br>
     * If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence
     * exists because either str is empty or it contains only whitespace characters, no conversion is performed.
     *
     * @param str C string containing the representation of an integral number.
     * @return On success, the function returns the converted integral number as a long int value.<br>
     * If no valid conversion could be performed, a zero value is returned.<br>
     * If the correct value is out of the range of representable values, LONG_MAX or LONG_MIN is returned.
     */
    EXPORT_LOCAL long atol(const char *str);
    /**
     * Convert string to double.<br>
     * Parses the C string str interpreting its content as a floating point number and returns its value as a
     * double. If endptr is not a null pointer, the function also sets the value pointed by endptr to point to
     * the first character after the number.<br>
     * The function first discards as many whitespace characters as necessary until the first non-whitespace
     * character is found. Then, starting from this character, takes as many characters as possible that are valid
     * following a syntax resembling that of floating point literals, and interprets them as a numerical value.
     * A pointer to the rest of the string after the last valid character is stored in the object pointed by endptr.<br>
     * A valid floating point number for strtod is formed by a succession of:<br>
     * - An optional plus or minus sign<br>
     * - A sequence of digits, optionally containing a decimal-point character<br>
     * - An optional exponent part, which itself consists on an 'e' or 'E' character followed by an optional sign
     * and a sequence of digits.<br>
     * If the first sequence of non-whitespace characters in str does not form a valid floating-point number as just
     * defined, or if no such sequence exists because either str is empty or contains only whitespace characters,
     * no conversion is performed.
     *
     * @param s C string beginning with the representation of a floating-point number.
     * @param sret Reference to an already allocated object of type char*, whose value is set by the function to the
     * next character in str after the numerical value. This parameter can also be a null pointer, in which case it is not used.
     * @return On success, the function returns the converted floating point number as a double value.<br>
     * If no valid conversion could be performed, a zero value (0.0) is returned.<br>
     * If the correct value is out of the range of representable values, a positive or negative HUGE_VAL is returned,
     * and the global variable errno is set to ERANGE.<br>
     * If the correct value would cause underflow, zero is returned and errno is set to ERANGE.
     */
    EXPORT_LOCAL double strtod(const char *s, char **sret);
    /**
     * Convert string to long integer<br>
     * Parses the C string str interpreting its content as an integral number of the specified base, which is returned as a
     * long int value.<br>
     * The function first discards as many whitespace characters as necessary until the first non-whitespace character is
     * found. Then, starting from this character, takes as many characters as possible that are valid following a syntax
     * that depends on the base parameter, and interprets them as a numerical value. Finally, a pointer to the first character
     * following the integer representation in str is stored in the object pointed by endptr.<br>
     * If the value of base is zero, the syntax expected is similar to that of integer constants, which is formed by a succession of:<br>
     * - An optional plus or minus sign<br>
     * - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)<br>
     * - A sequence of decimal digits (if no base prefix was specified) or either octal or hexadecimal digits if a
     * specific prefix is present<br>
     * If the base value is between 2 and 36, the format expected for the integral number is a succession of the valid
     * digits and/or letters needed to represent integers of the specified radix (starting from '0' and up to 'z'/'Z' for
     * radix 36). The sequence may optionally be preceded by a plus or minus sign and, if base is 16, an optional "0x" or "0X" prefix.<br>
     * If the first sequence of non-whitespace characters in str is not a valid integral number as defined above, or if no
     * such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
     *
     * @param str C string containing the representation of an integral number.
     * @param endptr Reference to an object of type char*, whose value is set by the function to the next character in str after
     * the numerical value.<br>
     * This parameter can also be a null pointer, in which case it is not used.
     * @param base The base to use for the transormation.
     * @return On success, the function returns the converted integral number as a long int value.<br>
     * If no valid conversion could be performed, a zero value is returned.<br>
     * If the correct value is out of the range of representable values, LONG_MAX or LONG_MIN is returned, an the global
     * variable errno is set to ERANGE.
     */
    EXPORT_LOCAL long strtol(const char *str, char **endptr, int base);
    /**
     * Convert string to unsigned long integer.<br>
     * Parses the C string str interpreting its content as an unsigned integral number of the specified base, which is returned as an
     * unsigned long int value.<br>
     * The function first discards as many whitespace characters as necessary until the first non-whitespace character is found.
     * Then, starting from this character, takes as many characters as possible that are valid following a syntax that depends on
     * the base parameter, and interprets them as a numerical value. Finally, a pointer to the first character following the integer
     * representation in str is stored in the object pointed by endptr.<br>
     * If the value of base is zero, the syntax expected is similar to that of integer constants, which is formed by a succession of:<br>
     * - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)<br>
     * - A sequence of decimal digits (if no base prefix was specified) or either octal or hexadecimal digits if a specific prefix is present<br>
     * If the base value is between 2 and 36, the format expected for the integral number is a succession of the valid digits and/or
     * letters needed to represent integers of the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). If the base
     * is 16, the sequence may optionally be preceded by "0x" or "0X", which is ignored.<br>
     * If the first sequence of non-whitespace characters in str is not a valid integral number as defined above, or if no such
     * sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
     *
     * @param str C string containing the representation of an unsigned integral number.
     * @param endptr Reference to an object of type char*, whose value is set by the function to the next character in str after the
     * numerical value.<br>
     * This parameter can also be a null pointer, in which case it is not used.
     * @param base The base to use for the transormation.
     * @return On success, the function returns the converted integral number as a long int value.<br>
     * If no valid conversion could be performed, a zero value is returned.<br>
     * If the correct value is out of the range of representable values, ULONG_MAX is returned, an the global variable errno is set to ERANGE.
     */
    EXPORT_LOCAL unsigned long strtoul(const char *str, char **endptr, int base);
    /**
     * 
     * @param s
     * @param endptr
     * @param base
     * @param width
     * @param flag
     * @return The number.
     */
    EXPORT_LOCAL size_t strtoi(const char *s, char **endptr, int base, int width, char flag);
	/**
	 * Skip the next numbers.
	 *
	 * @param s The string on that you want to skip the number characters.
	 * @return The number that was skipped.
	 */
	EXPORT_LOCAL int skip_atoi(const char **s);
	/**
	 * Print a number to the c string.
	 *
	 * @param str The string buffer to print the number to.
	 * @param num The number to print.
	 * @param base The base to use for the transormation.
	 * @param size The size of the string buffer.
	 * @param precision The precision to use for the transformation.
	 * @param type Type flag for options.
	 * @return The str value after the number writing.
	 */
	EXPORT_LOCAL char *number(char *str, long num, int base, int size, int precision, int type);
	/**
	 * Print a address.
	 *
	 * @param str The string buffer to print a address to.
	 * @param addr The address to paint.
	 * @param size The size of the string buffer.
	 * @param precision The precision to use for the transformation.
	 * @param type Type flag for options.
	 * @return The str value after the number writing.
	 */
	EXPORT_LOCAL char *eaddr(char *str, unsigned char *addr, int size, int precision, int type);
	/**
	 * Print a address.
	 *
	 * @param str The string buffer to print a address to.
	 * @param addr The address to paint.
	 * @param size The size of the string buffer.
	 * @param precision The precision to use for the transformation.
	 * @param type Type flag for options.
	 * @return The str value after the number writing.
	 */
	EXPORT_LOCAL char *iaddr(char *str, unsigned char *addr, int size, int precision, int type);
	/**
	 *
	 * @param value
	 * @param buffer
	 * @param fmt
	 * @param precision The precision to use for the transformation.
	 */
	EXPORT_LOCAL void cfltcvt(double value, char *buffer, char fmt, int precision);
	/**
	 *
	 * @param buffer
	 */
	EXPORT_LOCAL void forcdecpt(char *buffer);
	/**
	 *
	 * @param buffer
	 */
	EXPORT_LOCAL void cropzeros(char *buffer);
	/**
	 * 
	 * @param str
	 * @param num
	 * @param size
	 * @param precision
	 * @param fmt
	 * @param flags
	 * @return The resulting string.
	 */
	EXPORT_LOCAL char *flt(char *str, double num, int size, int precision, char fmt, int flags);
	/**
	 *
	 * @param arg
	 * @param ndigits
	 * @param decpt
	 * @param sign
	 * @param buf
	 * @param eflag
	 * @return The resulting string.
	 */
	EXPORT_LOCAL char *cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag);
	/**
	 *
	 * @param arg
	 * @param ndigits
	 * @param decpt
	 * @param sign
	 * @return The resulting string.
	 */
	EXPORT_LOCAL char *ecvt(double arg, int ndigits, int *decpt, int *sign);
	/**
	 *
	 * @param arg
	 * @param ndigits
	 * @param decpt
	 * @param sign
	 * @param buf
	 * @return The resulting string.
	 */
	EXPORT_LOCAL char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
	/**
	 *
	 * @param arg
	 * @param ndigits
	 * @param decpt
	 * @param sign
	 * @return The resulting string.
	 */
	EXPORT_LOCAL char *fcvt(double arg, int ndigits, int *decpt, int *sign);
	/**
	 *
	 * @param arg
	 * @param ndigits
	 * @param decpt
	 * @param sign
	 * @param buf
	 * @return The resulting string.
	 */
	EXPORT_LOCAL char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);

#if defined __cplusplus
}

#define abort() __abort_fail(__FILE__, __LINE__, __FUNCTION__)

#endif

#endif
